package com.hugh.glrpcconsumer.config;

import com.hugh.glrpcconsumer.annotation.GlReference;
import com.hugh.glrpcconsumer.proxy.ProxyFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @Author: Hugh
 * @Date: 2020/6/14
 */
@Slf4j
@Component
public class ReferenceBeanConfig implements ApplicationListener<ContextRefreshedEvent> {

    @Autowired
    private ProxyFactory proxyFactory;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent){
        ApplicationContext applicationContext = contextRefreshedEvent.getApplicationContext();

        Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(Service.class);

        beansWithAnnotation.forEach( (key, val) -> {
            Field[] fields = val.getClass().getDeclaredFields();
            for (Field field : fields){
                GlReference annotation = field.getAnnotation(GlReference.class);
                if(Objects.isNull(annotation)){
                    continue;
                }
                String provideName = field.getType().getName();
                Object proxy = proxyFactory.createProxy(getServiceClass(provideName), provideName);
                field.setAccessible(true);
                try {
                    field.set(val, proxy);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private Class<?> getServiceClass(String name) {
        try {
            return Class.forName(name);
        }
        catch (Exception e){
            return null;
        }
    }

}
